#!/usr/bin/perl

package Migration;

use strict;
use warnings;
use lib "../libs";

use Exporter qw(import);
use JSON;
use File::Find;
use File::Basename;
use Const ();
use App ();
use Utils ();
use Utils qw(dd);
use Export;
use Data::Dumper qw(Dumper);
use Log;
use Time::Piece;
use Encode qw(encode decode);
use POSIX qw(strftime);


use utf8;
use open qw(:std :utf8);
binmode STDOUT, ":utf8";

# Enable SQL profiling
$DBI::Profile = 2;

sub list {
    my $migration_path = $Const::CONF_PATH . $Const::DS . "migrations";
    my %migrations;
    find(sub {
        if (-f) {
            my $basename = basename($File::Find::name);
            unless ($basename =~ /\.json$/) {
                next;
            }
            $migrations{$basename} = decode_json(Utils::readFile($File::Find::name));
        }
    }, $migration_path);

    Log::info("Migration list:");
    for my $key (keys %migrations) {
        Log::primary("---- migration file: $key ----");
        my %migration = %{ $migrations{$key} };
        Log::info("> Src: type: $migration{src}->{host}, port: $migration{src}->{port}, user: $migration{src}->{user}, pass: $migration{src}->{pass}");
        Log::info("< Dst: type: $migration{dst}->{host}, port: $migration{dst}->{port}, user: $migration{dst}->{user}, pass: $migration{dst}->{pass}");

        unless (exists($migration{'tables'})) {
            Log::warn("- No tables to migrate!");
            next;
        }
        Log::info("- Tables:");
        my @tables = @{ $migration{'tables'} };
        for my $table (@tables) {
            print "\t$table\n";
        }
    }
}

sub getMaxProcesses
{
    my $app_config_path = $Const::CONF_PATH . $Const::DS . "app.config";
    my $app_config = decode_json(Utils::readFile($app_config_path));
    return defined $app_config->{migration}->{max_processes} ? $app_config->{migration}->{max_processes} : 5;
}

sub run 
{
    my ($migration_name, $table_name) = @ARGV;
    my $migration_path = $Const::CONF_PATH . $Const::DS . "migrations";
    my %migrations;
    my $time = strftime("%Y%m%d", localtime);

    my $debug = shift;
    if (defined $debug && $debug eq "--debug") {
        Log::setLevel($Log::all);
    } else {
        Log::setLevel(15);
    }
    find(sub {
        if (-f) {
            my $basename = basename($File::Find::name);
            unless ($basename =~ /\.json$/) {
                next;
            }
            if (!defined $migration_name || $basename eq $migration_name) {
                $migrations{$basename} = decode_json(Utils::readFile($File::Find::name));    
            }
        }
    }, $migration_path);

    for my $key (keys %migrations) {
        
        my %migration = %{ $migrations{$key} };
        Log::info(">>>>>>>> Migration file: $key <<<<<<<<");

        my $max_processes = getMaxProcesses(); # Maximum number of parallel processes
        Log::info("max fork process: ${max_processes}");
        my @pids;
        my @tables;
        if (defined $table_name) {
            @tables = ($table_name);
        } else {
            @tables = @{ $migration{'tables'} };
        }
        my $table_count = scalar(@tables);

        for (my $i = 0; $i < $table_count; $i++) {
            my $table = $tables[$i];
            my $src_schema = $migration{'src'}{'schema'};
            my $dst_schema = $migration{'dst'}{'schema'};

            Log::info("Table: $table. in [ $i/$table_count ]");

            if (scalar(@pids) < $max_processes) {
                my $pid = fork();
                if ($pid == 0) {
                    my $mypid = $$;

                    Log::info("---- Child process [$mypid] started for table ${table}. ----");
                    my $src_db = App::getDB($migration{'src'});
                    my $dst_db = App::getDB($migration{'dst'});

                    # ---------------- diff count start ----------------
                    # Compare row count
                    Log::info("> Start migrate table [$table] data count.");
                    my $src_count = App::getCount($src_db, $table, $src_schema);
                    my $dst_count = App::getCount($dst_db, $table, $dst_schema);
                    Log::info("  src count: $src_count, dst count: $dst_count");
                    if ($src_count != $dst_count) {
                        Log::warn("  Table [$table] data count mismatch!");
                    } else {
                        Log::primary("  Table [$table] data count match!");
                    }
                    # ---------------- diff count end ----------------

                    # Get columns
                    my $src_columns;
                    if ($src_db->{config}{type} eq "Oracle") {
                        my $sql = "SELECT column_name, data_type FROM all_tab_columns WHERE owner=UPPER('${src_schema}') AND table_name=UPPER('${table}') ORDER BY column_id";
                        $src_columns = $src_db->{dbh}->selectall_arrayref($sql);
                        Log::info("  Get src table columns sql: $sql;");
                    } elsif ($src_db->{config}{type} eq "PostgreSQL") {
                        my $sql = "SELECT column_name, data_type FROM information_schema.columns WHERE table_schema=LOWER('${src_schema}') AND table_name=LOWER('${table}') ORDER BY ordinal_position";
                        Log::info("  Get src table columns sql: $sql;");
                        $src_columns = $src_db->{dbh}->selectall_arrayref($sql);
                    } else {
                        Log::error("Unsupported database type: " . $src_db->{config}{type});
                        exit 1;
                    }
                    
                    # ---------------- diff sum start ----------------
                    # Compare sum for NUMBER columns
                    my $diff_sum = 1;
                    my @diff_sum_result;
                    Log::info("> Start migrate table [$table] data sum.");
                    my @src_number_columns;
                    for my $column (@$src_columns) {
                        my ($column_name, $data_type) = @$column;
                        if ($data_type eq ($src_db->{config}->{type} eq "Oracle" ? "NUMBER" : "numeric")) {
                            push(@src_number_columns, $column_name);
                        }
                    }
                    Log::info("    src table [$table] number columns: " . join(", ", @src_number_columns));
                    for my $number_column (@src_number_columns) {
                        Log::info(">> Start migrate table [$table] column [$number_column] sum.");
                        my $src_sum = App::getSum($src_db, $table, $number_column, $src_schema);
                        my $dst_sum = App::getSum($dst_db, $table, $number_column, $dst_schema);
                        Log::info("  src sum: $src_sum, dst sum: $dst_sum");
                        if ($src_sum != $dst_sum) {
                            Log::warn("  Table [$table] column [$number_column] sum mismatch!");
                            $diff_sum = 0;
                        } else {
                            Log::primary("  Table [$table] column [$number_column] sum match!");
                        }
                        
                        push (@diff_sum_result, {
                            collumn => $number_column,
                            src_sum => $src_sum,
                            dst_sum => $dst_sum
                        })
                    }
                    # ---------------- diff sum end ----------------

                    # ---------------- diff date start ----------------
                    # Compare sum for datetime columns
                    Log::info("> Start migrate table [$table] data for datetime.");
                    my @src_datetime_columns;
                    for my $column (@$src_columns) {
                        my ($column_name, $data_type) = @$column;
                        if ($src_db->{config}{type} eq "Oracle") {
                            if ($data_type eq "DATE") {
                                push(@src_datetime_columns, $column_name);
                            }
                        } elsif ($src_db->{config}{type} eq "PostgreSQL") {
                            if ($data_type eq "timestamp" || $data_type eq "date") {
                                push(@src_datetime_columns, $column_name);
                            }
                        }
                    }
                    Log::info("  src table [$table] datetime columns: " . join(", ", @src_datetime_columns));

                    my $diff_datetime = 1;
                    my @diff_datetime_result;
                    if (scalar(@src_datetime_columns) > 0) {
                        if ($src_db->{config}{type} eq "PostgreSQL") {
                            for my $datetime_column (@src_datetime_columns) {
                                my $src_datetime_sql = "select ${datetime_column}::date::timestamp, count(*) as count from ${src_schema}.${table} where (${datetime_column} is not null and ${datetime_column}::text <> '1970-01-01') group by ${datetime_column} order by count desc limit 10";
                                my $src_datetime_rows = App::selectAll($src_db, $src_datetime_sql);
                                my $dst_datetime_sql = "select ${datetime_column}::date::timestamp, count(*) as count from ${dst_schema}.${table} where (${datetime_column} is not null and ${datetime_column}::text <> '1970-01-01') group by ${datetime_column} order by count desc limit 10";
                                my $dst_datetime_rows = App::selectAll($dst_db, $dst_datetime_sql);
                                if (scalar(@$src_datetime_rows) != scalar(@$dst_datetime_rows)) {
                                    Log::warn("  Table [$table] column [$datetime_column] datetime count mismatch!");
                                    $diff_datetime = 0;
                                } else {
                                    Log::primary("  Table [$table] column [$datetime_column] datetime count match!");
                                }
                                
                                for (my $i = 0; $i < scalar(@$src_datetime_rows); $i++) {
                                    my $src_datetime_row = $src_datetime_rows->[$i];
                                    my ($src_datetime, $src_count) = ('', 0);
                                    if (defined $src_datetime_row) {
                                        ($src_datetime, $src_count) = @$src_datetime_row;
                                    }
                                    my $dst_datetime_row = $dst_datetime_rows->[$i];
                                    my ($dst_datetime, $dst_count) = ('', 0);
                                    if (defined $dst_datetime_row) {
                                        ($src_datetime, $dst_count) = @$src_datetime_row;
                                    }
                                    Log::info("  Table [$table] column [$datetime_column]: $src_datetime, src count: $src_count, dst count: $dst_count");
                                    if ($src_count ne $dst_count) {
                                        Log::warn("  Table [$table] column [$datetime_column] datetime mismatch!");
                                    } else {
                                        Log::info("  Table [$table] column [$datetime_column] datetime match!");
                                    }

                                    push(@diff_datetime_result, {
                                        collumn => $datetime_column,
                                        datetime => $src_datetime,
                                        src_count => $src_count,
                                        dst_count => $dst_count
                                    })
                                }
                            }
                        }
                    } else {
                        Log::primary("  src table [$table] datetime columns: not found!");
                    }
                    # ---------------- diff date end ----------------

                    # ---------------- diff row start ----------------
                    # Compare rows for VARCHAR2 columns
                    Log::info("> Start migrate table [$table] data for row.");
                    my @src_varchar_columns;
                    for my $column (@$src_columns) {
                        my ($column_name, $data_type) = @$column;
                        if ($data_type eq ($src_db->{config}{type} eq "Oracle" ? "VARCHAR2" : "character varying")) {
                            push(@src_varchar_columns, $column_name);
                        }
                    }
                    Log::info("  src table [$table] varchar columns: " . join(", ", @src_varchar_columns));

                    # Get a base row
                    my $base_row = App::getBaseRow($src_db, $table, $src_schema);

                    # Generate conditions for detailed comparison
                    my @conditions = ();
                    my $canvalidate = 0;
                    my $sql = "SELECT COUNT(*) AS COUNT FROM $src_db->{config}{schema}.${table} WHERE 1=1 ";
                    my @where= ();
                    my $where_str = "";

                    for my $varchar_column (@src_varchar_columns) {
                        if (defined($base_row->{$varchar_column}) && $base_row->{$varchar_column} ne "") {
                            $where_str = "$varchar_column = '$base_row->{$varchar_column}'";
                            push(@where, $where_str);
                        } else {
                            $where_str = "($varchar_column IS NULL OR $varchar_column = '')";
                            push(@where, $where_str);
                        }

                        my $count;
                        if ($src_db->{config}->{type} eq "Oracle") {
                            $sql = $sql. " AND ". $where_str;
                        } elsif ($src_db->{config}->{type} eq "PostgreSQL") {
                            $sql = $sql. " AND ". $where_str;
                        } else {
                            Log::error("Unsupported database type: " . $src_db->{config}->{type});
                            exit 1;
                        }
                        $count = defined App::selectRow($src_db, $sql)->{'count'} ? App::selectRow($src_db, $sql)->{'count'} : App::selectRow($src_db, $sql)->{'COUNT'};
                        if ($count < $migration{'row_limit'}) {
                            Log::info("  Table [$table] get row count: $count, can validate. sql: $sql;");
                            $canvalidate = 1;
                            last;
                        }
                    }

                    my $match;
                    my @diff_row_result;
                    my $diff_row = 1;
                    if ($canvalidate) {
                        my $src_limit_str;
                        my $dst_limit_str;
                        my $src_sql;
                        my $dst_sql;
                        if ($src_db->{config}->{type} eq "Oracle") {
                            $src_limit_str = " AND ROWNUM <= ". $migration{'row_limit'};
                            my $order_by_str = "";
                            for my $varchar_column (@src_varchar_columns) {
                                $order_by_str = $order_by_str. ($order_by_str eq ""? "" : ", "). "RAWTOHEX(UTL_I18N.STRING_TO_RAW($varchar_column, 'AL32UTF8'))";
                            }
                            if ($order_by_str ne "") {
                                $order_by_str = " ORDER BY ". $order_by_str;
                            }
                            $src_sql = "SELECT * FROM $src_db->{config}{schema}.${table} WHERE 1=1 AND ". (join(" AND ", @where)). " ${src_limit_str} ${order_by_str}";

                        } elsif ($src_db->{config}->{type} eq "PostgreSQL") {
                            my $order_by_str = "";
                            for my $varchar_column (@src_varchar_columns) {
                                $order_by_str = $order_by_str. ($order_by_str eq ""? "" : ", "). $varchar_column. " NULLS FIRST ";
                            }
                            $src_limit_str = " LIMIT ". $migration{'row_limit'};
                            $src_sql = "SELECT * FROM $src_db->{config}{schema}.${table} WHERE 1=1 AND ". (join(" AND ", @where)). " ORDER BY ${order_by_str} ${src_limit_str}";
                        } else {
                            Log::error("Unsupported database type: " . $src_db->{config}->{type});
                            exit 1;
                        }
                        if ($dst_db->{config}->{type} eq "Oracle") {
                            $dst_limit_str = " AND ROWNUM <= ". $migration{'row_limit'};
                            my $order_by_str = "";
                            for my $varchar_column (@src_varchar_columns) {
                                $order_by_str = $order_by_str. ($order_by_str eq ""? "" : ", "). "RAWTOHEX(UTL_I18N.STRING_TO_RAW($varchar_column, 'AL32UTF8'))";
                            }
                            if ($order_by_str ne "") {
                                $order_by_str = " ORDER BY ". $order_by_str;
                            }
                            $dst_sql = "SELECT * FROM $dst_db->{config}{schema}.${table} WHERE 1=1 AND ". (join(" AND ", @where)). " ${dst_limit_str} ${order_by_str}";
                        } elsif ($dst_db->{config}->{type} eq "PostgreSQL") {
                            $dst_limit_str = " LIMIT ". $migration{'row_limit'};
                            my $order_by_str = "";
                            for my $varchar_column (@src_varchar_columns) {
                                $order_by_str = $order_by_str. ($order_by_str eq ""? "" : ", "). $varchar_column. " NULLS FIRST ";
                            }
                            $dst_sql = "SELECT * FROM $dst_db->{config}{schema}.${table} WHERE 1=1 AND ". (join(" AND ", @where)). " ORDER BY ${order_by_str} ${dst_limit_str}";
                        } else {
                            Log::error("Unsupported database type: " . $src_db->{config}->{type});
                            exit 1;
                        }
                        Log::info("  src sql: $src_sql");
                        Log::info("  dst sql: $dst_sql");
                        my $src_rows = App::exec($src_db, $src_sql);
                        my $dst_rows = App::exec($dst_db, $dst_sql);
                        # Compare rows
                        ($match, @diff_row_result) = compare_rows($src_rows, $dst_rows, \@src_varchar_columns);
                        if ($match) {
                            Log::primary("  Table [$table] row match!");
                        } else {
                            Log::warn("  Table [$table] row mismatch!");
                            $diff_row = 0;
                        }
                    } else {
                        Log::info("Too many rows to perform detailed comparison for table $table.");
                    }
                    # ---------------- diff row end ----------------

                    # ---------------- output start ----------------
                    Log::info("Generated excel for table [ $table ] starting.");

                    my $excel = new Export(
                        filename => "${table}.xlsx" ,
                        subdir => $key,
                        time => $time
                    );

                    $excel->addWorksheet("行数对比",[
                        "表名",
                        "原表行数",
                        "目标表行数",
                        "是否一致",
                    ]);
                    $excel->addWorksheetData("行数对比", [
                        $table,
                        $src_count,
                        $dst_count,
                        $src_count == $dst_count? "是" : "否",
                    ]);
                    $excel->doExport("行数对比");

                    # ---------

                    $excel->addWorksheet("求和对比", [
                        "表名",
                        "列名",
                        "原表列求和结果",
                        "目标表列求和结果",
                        "是否一致",
                    ]);

                    for my $i (0..$#diff_sum_result) {
                        my $row = $i + 1;
                        $excel->addWorksheetData("求和对比", [
                            $table,
                            $diff_sum_result[$i]->{collumn},
                            $diff_sum_result[$i]->{src_sum},
                            $diff_sum_result[$i]->{dst_sum},
                            $diff_sum_result[$i]->{src_sum} == $diff_sum_result[$i]->{dst_sum}? "是" : "否",
                        ]);
                    }
                    $excel->doExport("求和对比");

                    # ---------
                    
                    $excel->addWorksheet("时间对比", [
                        "表名",
                        "列名",
                        "时间",
                        "原表分组计数",
                        "目标表分组计数",
                        "是否一致",
                    ]);
                    for my $i (0..$#diff_datetime_result) {
                        $excel->addWorksheetData("时间对比", [
                            $table,
                            $diff_datetime_result[$i]->{collumn},
                            $diff_datetime_result[$i]->{datetime},
                            $diff_datetime_result[$i]->{src_count},
                            $diff_datetime_result[$i]->{dst_count},
                            $diff_datetime_result[$i]->{src_count} == $diff_datetime_result[$i]->{dst_count}? "是" : "否",
                        ]);
                    }
                    $excel->doExport("时间对比");

                    # ---------

                    my @col_sheet_headers = (
                        "表名",
                    );
                    my $columns_count = scalar(@src_varchar_columns);
                    for my $i (0..$#src_varchar_columns) {
                        push @col_sheet_headers, "原表列[$src_varchar_columns[$i]]", "目标表列[$src_varchar_columns[$i]]", "列[$src_varchar_columns[$i]]是否一致";
                    }
                    $excel->addWorksheet("随机行列对比", \@col_sheet_headers);
                    for my $i (0..$#diff_row_result) {
                        my $row = $i + 1;
                        my @row_data = (
                            $table, 
                        );
                        for my $j (0..$#{$diff_row_result[$i]}) {
                            push @row_data, $diff_row_result[$i]->[$j];
                        }
                        $excel->addWorksheetData("随机行列对比", \@row_data);
                    }
                    $excel->doExport("随机行列对比");

                    Log::primary("Excels for table [ $table ] generated at [" . $excel->getRealpath() . "].");
                    $excel->close();

                    exit 0;
                } else {
                    push(@pids, $pid);
                }
            }
            else{
                my $pid = waitpid(-1,0);
                if($pid>0){
                    @pids=grep{$_ !=$pid} @pids;
                    redo;
                }else{
                    die "waitpid error:$!\n";
                }

            }
        }

        for my $pid (@pids) {
            waitpid($pid, 0);
        }
    }
    
    unless (defined $migration_name && defined $table_name) {
        generatedMainExcel(\%migrations, $time);
    }
}

sub compare_rows {
    my ($src_rows, $dst_rows, $src_varchar_columns) = @_;
    
    my $match = 1;

    my @diff_row_result;

    for my $i (0..$#$src_rows) {
        my $src_row = $src_rows->[$i];
        my $dst_row = $dst_rows->[$i];
        
        my @row_result;
        for my $varchar_column (@$src_varchar_columns) {
            my $src_value = defined($src_row->{$varchar_column})? $src_row->{$varchar_column} : $src_row->{lc($varchar_column)}; 
            my $dst_value = defined($dst_row->{$varchar_column})? $dst_row->{$varchar_column} : $dst_row->{lc($varchar_column)};

            unless (defined $src_value) {
                $src_value = "";
            }
            unless (defined $dst_value) {
                $dst_value = "";
            }

            if ($src_value eq $dst_value) {
                Log::debug("  Row [${i}], column [$varchar_column] match! src: " . $src_value . ", dst: " . $dst_value . ""); 
                $match = 1;
            } else {
                Log::warn("  Row [${i}], column [$varchar_column] mismatch! src: " . $src_value . ", dst: " . $dst_value . "");
                $match = 0;
            }
            push(@row_result, (
                $src_value,
                $dst_value,
                $match ? '是' : '否'
            ));
        }
        push(@diff_row_result, \@row_result);
    }

    return $match, @diff_row_result;
}

sub genMain
{
    my $time = shift;
    unless (defined $time) {
        Log::error("Invalid time");
        return;
    }
    my $migration_path = $Const::CONF_PATH . $Const::DS . "migrations";
    my %migrations;
    find(sub {
        if (-f) {
            my $basename = basename($File::Find::name);
            unless ($basename =~ /\.json$/) {
                next;
            }
            $migrations{$basename} = decode_json(Utils::readFile($File::Find::name));
        }
    }, $migration_path);

    generatedMainExcel(\%migrations, $time);
}

sub generatedMainExcel
{
    my ($migrations, $time) = @_;

    Log::info("Generated schema main excel starting.");
    
    my @all_main_data;
    while (my ($key, $migration) = each %$migrations) {
        my $excel = new Export(
            filename => "0_main.xlsx",
            subdir => $key,
            time => $time 
        );

        $excel->addWorksheet("总览", [
            "表名",
            "行数是否一致",
            "求和对比是否一致",
            "时间对比是否一致",
            "随机行列对比是否一致",
            "结果链接",
        ]);

        my @tables = @{$migration->{'tables'}};
        my $table_count = scalar(@tables);
        for my $table (@tables) {
            
            my ($diff_count, $diff_sum, $diff_datetime, $diff_row) = (1, 1, 1, 1);
            
            my $parser = Spreadsheet::ParseXLSX->new();
            my $excel_filename = $Const::DATA_PATH. $Const::DS. $time. $Const::DS. $key. $Const::DS. "${table}.xlsx";
            
            if (! -e $excel_filename) {
                Log::warn("Excel file not found: $excel_filename");
                next;
            }
            Log::info("Generate main excel for table [ $table ], table excel filename: ${table}.xlsx");
            my $workbook = $parser->parse($excel_filename);
            for my $worksheet ($workbook->worksheets()) {
                my $worksheet_name = $worksheet->get_name();
                if ($worksheet_name eq "行数对比") {
                    $diff_count = $worksheet->get_cell(1, 3)->value() eq "是"? 1 : 0;
                } elsif ($worksheet_name eq "求和对比") {
                    my $row_max = $worksheet->row_range();
                    for my $row (1.. $row_max) {
                        my $cell = $worksheet->get_cell($row, 4);
                        if ($cell && $cell->value() ne "是") {
                            $diff_sum = 0;
                            last;
                        }
                    }
                } elsif ($worksheet_name eq "时间对比") {
                    my $row_max = $worksheet->row_range();
                    for my $row (1.. $row_max) {
                        my $cell = $worksheet->get_cell($row, 6);
                        if ($cell && $cell->value() ne "是") {
                            $diff_datetime = 0;
                            last;
                        }
                    }
                } elsif ($worksheet_name eq "随机行列对比") {
                    my $row_max = $worksheet->row_range();
                    my $col_max = $worksheet->col_range();
                    for my $row (1.. $row_max) {
                        for (my $col_i = 3; $col_i <= $col_max; $col_i += 3) {
                            my $cell = $worksheet->get_cell($row, $col_i);
                            if ($cell && $cell->value() ne "是") {
                                $diff_row = 0;
                                last; 
                            }
                        }
                    }
                }
            }

            $excel->addWorksheetData("总览", [
                $table, 
                $diff_count? "是" : "否",
                $diff_sum? "是" : "否",
                $diff_datetime? "是" : "否",
                $diff_row? "是" : "否",
                "${table}.xlsx",
            ]);
            Log::primary("Excels for table [ $table ] generated at [" . $excel->getRealpath() . "].");
        }

        $excel->doExport("总览");
        Log::primary("Excel for migration [". $key. "] generated at [". $excel->getRealpath(). "].");

        $excel->close();
        undef $excel;
    }
}

sub archive
{
    my $archive_dir = shift;
    unless (defined $archive_dir) {
        Log::error("请输入归档的目录");
        return;
    }

    my $archive_path = $Const::DATA_PATH . $Const::DS . $archive_dir;
    unless (-e $archive_path) {
        Log::error("归档路径不存在：${archive_path}");
        return;
    }
    Log::info("Archive dir is: ${archive_path}");

    my $archive_base_path = "${Const::DATA_PATH}${Const::DS}archive";
    unless (-d $archive_base_path) {
        Utils::_mkdir(${archive_base_path});
    }

    my $dst_file = "${archive_base_path}${Const::DS}${archive_dir}.zip";
    if (-f $dst_file) {
        Log::warn("Dst file exist, unlink file: $dst_file");
        unlink $dst_file;
    }
    `zip -qr ${dst_file} ${archive_path}`;
    Log::primary("Archived dst file: ${dst_file}");
}

sub parse_date {
    my ($date) = @_;
    if ($date =~ /^(\d{2})-(\w{3})-(\d{2})$/) {
        my ($day, $mon, $year) = ($1, $2, $3);
        my %mon_map = (
            'JAN' => '01', 'FEB' => '02', 'MAR' => '03', 'APR' => '04',
            'MAY' => '05', 'JUN' => '06', 'JUL' => '07', 'AUG' => '08',
            'SEP' => '09', 'OCT' => '10', 'NOV' => '11', 'DEC' => '12'
        );
        $mon = $mon_map{uc($mon)};
        $year = "20$year"; 
        return "$year-$mon-$day";
    } elsif ($date =~ /^(\d{4})-(\d{2})-(\d{2})$/) {
        return $date;
    } else {
        die "Unknown date format: $date";
    }
}



1;

__END__
